#include "transactionmodel.h"

#include "cashplusplus.h"

TransactionModel::TransactionModel(QObject* parent)
	: QSqlRelationalTableModel(parent, QSqlDatabase::database(CashPlusPlus::DB_NAME))
{
	connect(this, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(slot_dataChanged(QModelIndex,QModelIndex)));
	connect(this, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(slot_rowsInsertedOrRemoved(QModelIndex,int,int)));
	connect(this, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(slot_rowsInsertedOrRemoved(QModelIndex,int,int)));

	setTable("transactions");

	setEditStrategy(OnRowChange);
	setSort(3, Qt::DescendingOrder);

	setHeaderData(0, Qt::Horizontal, tr("ID"));
	setHeaderData(1, Qt::Horizontal, tr("Account"));
	setHeaderData(2, Qt::Horizontal, tr("Amount"));
	setHeaderData(3, Qt::Horizontal, tr("Date/Time"));
	setHeaderData(4, Qt::Horizontal, tr("Category"));
	setHeaderData(5, Qt::Horizontal, tr("Description"));

	select();
}

void TransactionModel::addTransaction(int account, double amount, uint timestamp, const QString& category, const QString& descr)
{
	submitAll();

	QSqlQuery q(database());
	q.prepare("INSERT INTO transactions VALUES (NULL, ?, ?, ?, ?, ?)");
	q.addBindValue(account);
	q.addBindValue(amount);
	q.addBindValue(timestamp);
	q.addBindValue(category);
	q.addBindValue(descr);
	q.exec();
	q.finish();

	select();
}

void TransactionModel::addTransaction(int account)
{
	addTransaction(account, 0.0, QDateTime::currentDateTime().toTime_t(), "", "");
}

void TransactionModel::deleteTransactions(const QModelIndexList& currentSelection)
{
	submitAll();
	setEditStrategy(OnManualSubmit);

	for (int i = 0; i < currentSelection.count(); ++i)
	{
		if (currentSelection.at(i).column() != 0)
		{
			continue;
		}

		removeRow(currentSelection.at(i).row());
	}

	submitAll();
	setEditStrategy(OnRowChange);
}

void TransactionModel::addNDTransactions(const QList<QStringList>& transactions, int domerAccount, int flexAccount)
{
	QSqlQuery q(database());
	foreach(QStringList trans, transactions)
	{
		QString type = trans[0];
		QDateTime date = QDateTime::fromString(trans[1], CashPlusPlus::DATETIME_FORMAT);
		QString category = trans[2];
		QString s_amount = trans[3];
		double d_amount = -s_amount.replace('$',"").toDouble();
		QString description = trans[5];

		int accountId = -1;

		if (category == "Add to Balance")
		{
			d_amount = -d_amount;
		}

		if (flexAccount > -1 && type.contains("Flex", Qt::CaseInsensitive))
		{
			accountId = flexAccount;
		}
		else if (domerAccount > -1 && type.contains("Domer", Qt::CaseInsensitive))
		{
			accountId = domerAccount;
		}

		if (accountId != -1)
		{
			q.prepare("SELECT id FROM transactions WHERE account_id = ? AND amount = ? AND datetime = ? AND category = ? AND description = ?");
			q.addBindValue(accountId);
			q.addBindValue(d_amount);
			q.addBindValue(date.toTime_t());
			q.addBindValue(category);
			q.addBindValue(description);
			q.exec();
			if (!q.next())
			{
				addTransaction(accountId, d_amount, date.toTime_t(), category, description);
			}
		}
	}
}

bool TransactionModel::isNDAccount(int row)
{
	QSqlQuery q(database());
	q.prepare("SELECT type FROM accounts WHERE accounts.id = ?");
	q.addBindValue(row);
	q.exec();
	if (q.next())
	{
		int type = q.value(0).toInt();
		return (type == CashPlusPlus::FLEX || type == CashPlusPlus::DOMER);
	}

	return false;
}

void TransactionModel::updateAccountBalance(int row)
{
	int account_id = index(row, 1).data().toInt();

	if (!isNDAccount(account_id))
	{
		QSqlQuery q(database());
		q.prepare("UPDATE accounts SET amount = (SELECT SUM(amount) FROM transactions WHERE account_id = accounts.id) WHERE id = ?");
		q.addBindValue(account_id);
		q.exec();
	}
}

void TransactionModel::slot_dataChanged(const QModelIndex& topLeft, const QModelIndex&)
{
	if (topLeft.column() == 2)
	{
		submitAll();
		updateAccountBalance(topLeft.row());
	}
}

void TransactionModel::slot_rowsInsertedOrRemoved(const QModelIndex&, int start, int)
{
	updateAccountBalance(start);
}
